package com.conf;

import com.alibaba.fastjson.JSON;
import com.dao.OplogDao;
import com.util.AjaxResult;
import com.util.UtilDate;
import com.util.UtilJwt;
import com.util.UtilRandom;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class AppInterceptor implements HandlerInterceptor {

    private final static Logger log = LoggerFactory.getLogger(AppInterceptor.class);

    @Value("${secret}")
    private String secret;

    public static ConcurrentHashMap<String,Map<String,Object>> tokenUser = new ConcurrentHashMap<>();

    @Autowired
    OplogDao oplogDao;

    //凭证无效
    void getTimeOutToken(String msg,HttpServletResponse response){
        try {
            response.reset();
            response.setHeader("Content-Type", "application/json;charset=UTF-8");
            response.setCharacterEncoding("utf-8");
            response.getWriter().println(JSON.toJSONString(AjaxResult.getFail(504,msg)));
        } catch (IOException e) {
            log.error("异常",e);
        }
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){
        String uri = request.getRequestURI();
        log.info("请求【{}】",uri);
        log.info("秘钥【{}】",secret);
        String token = request.getHeader(Constant.Authorization);
        if(token == null || "".equals(token)){
            getTimeOutToken("缺少凭证",response);
            return false;
        }
        if(!UtilJwt.checkSign(secret,token)){
            log.info("凭证过期或无效【{}】",token);
            tokenUser.remove(token);
            getTimeOutToken("凭证过期或无效",response);
            return false;
        }
        String user_id,nick_name,phone;
        Map<String,Object> mapUser = tokenUser.get(token);
        if(mapUser == null || mapUser.isEmpty()) {
            mapUser = new HashMap<>();
            mapUser.put(Constant.UserId,UtilJwt.getUserid(secret, token));
            mapUser.put(Constant.Nickname,UtilJwt.getUsername(secret, token));
            mapUser.put(Constant.Phone,UtilJwt.getPhone(secret, token));
        }
//        if(!getAuthFlag(token,uri,mapUser,response)){
//            return false;
//        }
        user_id = mapUser.get(Constant.UserId).toString();
        nick_name = mapUser.get(Constant.Nickname).toString();
        phone = mapUser.get(Constant.Phone).toString();
        tokenUser.put(token,mapUser);
        request.setAttribute(Constant.UserId,user_id);
        request.setAttribute(Constant.Nickname,nick_name);
        request.setAttribute(Constant.Phone,phone);
        //
        String finalUsername = nick_name;
        String finalUserid = user_id;
        //文件请求不记录日志
        if(!uri.startsWith("/getImage") && !"get".equals(request.getMethod())) {
            String op_uri = request.getRequestURI();
            String op_type = request.getMethod();
            String op_param = getParam(request);
            //拦截器不能异步使用request不然会参数丢失
            CompletableFuture.runAsync(() -> {
                addLog(finalUserid, finalUsername, op_uri,op_type,op_param);
            });
        }
        return true;
    }

    /**
     * @author 王乾
     * @comments 判断权限
     * @date 2024-05-12 15:22:33
     * @return boolean
     * @modification
     */
    boolean getAuthFlag(String token,String uri,Map<String,Object> mapUser,HttpServletResponse response){
        Object obj_menu_id = mapUser.get(Constant.MenuId);
        if(obj_menu_id == null){
            log.info("未分配-无权限【{}】",token);
            try {
                response.reset();
                response.setCharacterEncoding("utf-8");
                response.getWriter().println(JSON.toJSONString(AjaxResult.getFail("无权限")));
            } catch (IOException e) {
                log.error("异常",e);
            }
            return false;
        }
        List<String> listMenuId = (ArrayList)obj_menu_id;
        if(!listMenuId.contains(uri)){
            log.info("有分配-无权限【{}】",token);
            try {
                response.reset();
                response.setCharacterEncoding("utf-8");
                response.getWriter().println(JSON.toJSONString(AjaxResult.getFail("无权限")));
            } catch (IOException e) {
                log.error("异常",e);
            }
            return false;
        }
        return true;
    }

    /**
     * @author 王乾
     * @comments 记录日志
     * @date 2024/5/11 9:47
     * @modification
     */
    void addLog(String op_user_id,String op_username,String op_uri,String op_type,String op_param){
        String op_mod = "",op_gong = "";
        //
        Map<String,Object> param = new HashMap<>();
        param.put("op_id", UtilRandom.uuid());
        param.put("op_type",op_type);
        param.put("op_uri",op_uri);
        param.put("op_param",op_param);
        param.put("op_username",op_username);
        param.put("op_user_id",op_user_id);
        param.put("op_time", UtilDate.now());
        param.put("op_mod", op_mod);
        param.put("op_gong", op_gong);
        oplogDao.save(param);
    }

    /**
     * @author 王乾
     * @comments 获取参数
     * @date 2024/5/11 9:57
     * @modification
     */
    String getParam(HttpServletRequest request){
        StringBuffer params = new StringBuffer();
        Enumeration pNames = request.getParameterNames();
        while(pNames.hasMoreElements()){
            String name = (String)pNames.nextElement();
            String value = request.getParameter(name);
            params.append("&").append(name).append("=").append(value);
        }
        if(params.length()>1){
            return params.substring(1);
        }
        return "";
    }

}
